(function($, jsPlumb){
    'use strict';
    // 形状、边框大小配置 
    var _SETTIMEOUT_TARGET = null,
        _FLOWSHAPE_CONFIG={
            toptbarheight: 50,
            lefttbarwidth: 200,
            circleminradius: 16,
            rectminheight:50,
        },
        _DEFAULT_CONFIG={
            recordidprex: "cscecRecord_",
            proppathurl: "Public/testflow/propertyhtm/",
        };

    // 枚举内容
    const _TOOLBAR_TYPE = {
        // 分类type
        layout: "l",
        flow: "f",
        // 内容type
        table: "table",
        circle: "circle",
        rectange: "rectange",
        diamond: "diamond",
    }

    // 实现jQuery的cloest方法，selfflag是否判断自身
    var similarjQueryClosest = function(node, tag, selfflag){
        if(node && Object.prototype.toString.call(tag) == "[object String]"){
            var retnode = null;
            // tag类型，control, #controlid, .controlclassname, control[option]
            if(selfflag&&Object.prototype.toString.call(selfflag) == "[object Boolean]"){
                //包括自身判断
                retnode = checkNodeAttribute(node, tag);
                if(retnode) return retnode;
            }
            var parentNode = node.parentElement || node.parentNode;
            while(parentNode){
                // if(parentNode.className == tag.substr(1)){
                //     retnode = parentNode;
                //     break;
                // }
                retnode = checkNodeAttribute(parentNode, tag);
                if(retnode) break;
                parentNode = parentNode.parentElement || parentNode.parentNode;
            }
            return retnode;
        }
        return null;
    };
    function checkNodeAttribute(node, tag){
        var returnvalue = null;
        var prevcharcode = tag.charCodeAt(0);
        switch(prevcharcode){
            case 35: {
                //#
                if(node.id===tag.substr(1)) returnvalue=node;
                break;
            }
            case 46: {
                //.
                if(node.className.indexOf(tag.substr(1))>=0) returnvalue=node;
                break;
            }
            default:{
                // if((prevcharcode>=65&&prevcharcode<=90) || (prevcharcode>=97&&prevcharcode<=122)){}
                var arrtleftnum=tag.indexOf("[");
                if(arrtleftnum>=0 && tag.indexOf("]")>=0){
                    //属性
                    var nodetagName = tag.substr(0, arrtleftnum),
                        attributeName = tag.substring(arrtleftnum+1, tag.length-1);
                    if(node.tagName === nodetagName.toUpperCase() && node.hasAttribute(attributeName))
                        returnvalue=node;
                }
                //dom元素
                if(node.tagName === tag.toUpperCase()) {
                    returnvalue=node
                };
            }
        }
        return returnvalue;
    }

    // 初始化jsPlumb实列
    var jsPlumb_instance = window.jsp = jsPlumb.getInstance({
        // default drag options
        Endpoint: ["Dot", {radius: 3, cssClass:"jsk-dot"}],
        //Connector:"StateMachine",
        HoverPaintStyle: {stroke: "#61B7CF", strokeWidth: 3 },
        ConnectorZIndex:5,
        ConnectionOverlays: [
            [ "Arrow", {
                id: "arrow",
                location: 1,
                width:11,
                length:11,
                foldback: 0.8
            } ]
        ],
        Container: "flow-target"
    });

    // 向目标框添加拖拽的内容 type：_TOOLBAR_TYPE（常量类型）
    function addDragContenttoTarget(dragobj, ev, type){
        var top = ev.layerY || ev.offsetY,
            left = ev.layerX || ev.offsetX;
        var targetEl = ev.target || ev.srcElement;
        if (dragobj) {
            if('content' in document.createElement('template')){
                var parentEl = null;
                if(type===_TOOLBAR_TYPE.layout){
                    parentEl=dragobj;
                }else if(type==_TOOLBAR_TYPE.flow){
                    parentEl=dragobj.parentNode ||　dragobj.parentElement;
                }
            
                var tlelement = parentEl.querySelector("template");
                var clonefragment = document.importNode(tlelement.content, true);
                //var cloneobj = dragobj.cloneNode(true);
                var fragmentdiv = clonefragment.querySelector("div");
                fragmentdiv.style.position = "absolute";
                fragmentdiv.style.top = top + "px";
                fragmentdiv.style.left = left + "px";
                fragmentdiv.id= getFlowItemtypeId(parentEl);

                // 初始化mousedown事件，可进行缩放
                fragmentdiv.querySelector(".ui-resizable-icon").onmousedown=function(e){
                    e=e||window.event;
                    var target=e.target||e.srcElement;
                    resizableTarget(null, target);
                };

                targetEl.appendChild(clonefragment);
                
                // jsPlumb 设置组件可拖动
                jsPlumb_instance.draggable(fragmentdiv, {
                    beforeStart: function(jsPdragObj, p2, p3){ },
                    start: function(jsPdragObj){
                        var event = jsPdragObj.e||window.event;
                        var target = event.target||event.srcElement;
                        if(target&&target.className==="ui-resizable-icon"){ 
                            return false    //  阻止点击缩放图标时，拖动元素
                        }
                    }, 
                    drag: function(jsPdragObj, p2, p3){
                        // 后续是否需要优化
                        jsPlumb_instance.repaintEverything();
                     }, 
                    //drop: function(){ }, 
                    stop: function(jsPdragObj, p2, p3){
                        // 后续是否需要优化
                        jsPlumb_instance.repaintEverything();
                    }, 
                });

                if(type === _TOOLBAR_TYPE.flow){ // 仅流程图类型的元素可描线
                    addjsPlumbStartline(fragmentdiv);
                    //_addEndpoints(fragmentdiv.id, ["TopCenter", "BottomCenter"], ["LeftMiddle", "RightMiddle"]);
                }
                 
            }else{
                //ie不支持template,其他方法实现
            }
        }
    }
    
    // jsPlumb给dom节点指定的对象添加描线功能
    function addjsPlumbStartline(el){
        jsPlumb_instance.makeSource(el, {
            filter: ".jsk-startPoint",
            anchor: "Continuous",
            connector: [ "Flowchart", { stub: [20, 0], gap: 5, cornerRadius: 5, alwaysRespectStubs: false } ],
            connectorStyle: { strokeWidth: 2, stroke: "#61B7CF", joinstyle: "round", },
            //connectionType: "basic",
            maxConnections: 3,
            onMaxConnections: function (info, e) {
                alert("Maximum connections (" + info.maxConnections + ") reached");
            }
        });
        //_addEndpoints(fragmentdiv.id, ["TopCenter", "BottomCenter"], ["LeftMiddle", "RightMiddle"]);
        
        jsPlumb_instance.makeTarget(el, {
            //dropOptions: { hoverClass: "dragHover" },
            anchor:["Continuous",{faces:["top", "right", "bottom"]}],
            allowLoopback: false,   // 是否允许连接自身
        });

        // this is not part of the core demo functionality; it is a means for the Toolkit edition's wrapped
        // version of this demo to find out about new nodes being added.
        jsPlumb_instance.fire("jsPlumbDemoNodeAdded", el);
    }

    // 对目标框进行拖拽缩放功能
    function resizableTarget(_that, target){
        _that=_that||document.querySelector(".flow-target");
        var tmpEl = target;
        var parentEl = target.parentNode||target.parentElement;
        var elleft=0, eltop=0;

        var pEl = similarjQueryClosest(parentEl, "div[controltype]", false);
        if(pEl){
            elleft = parentEl.offsetLeft+pEl.offsetLeft;
            eltop = parentEl.offsetTop+pEl.offsetTop;
        }else{
            elleft = parentEl.offsetLeft||parseInt(window.getComputedStyle(parentEl).left);
            eltop = parentEl.offsetTop||parseInt(window.getComputedStyle(parentEl).top);
        }

        _that.onmousemove = function(_event2){
            if(!_SETTIMEOUT_TARGET){
                _SETTIMEOUT_TARGET = setTimeout(function() {
                    _event2=_event2||window.event;
                    // var currentleft=_event2.offsetX||_event2.layerX,
                    //     currenttop=_event2.offsetY||_event2.layerY;
                    var dx = (_event2.pageX - elleft-_FLOWSHAPE_CONFIG.lefttbarwidth) || 0,
                        dy = (_event2.pageY - eltop-_FLOWSHAPE_CONFIG.toptbarheight) || 0;
                    parentEl.style.height=dy+"px";
                    parentEl.style.width=dx+"px";
                    var shapeType = parentEl.getAttribute("controltype")
                    switch(shapeType){
                        case _TOOLBAR_TYPE.diamond: {
                            var svgEl = parentEl.querySelector("svg"),
                                polygonEl = parentEl.querySelector("polygon");
                            svgEl.style.height=dy+"px";
                            svgEl.style.width=dx+"px";

                            var x1=Math.round(dx/2),
                                y1=Math.round(dy/2);
                            var pathStr = "0,"+y1+" "+x1+",0"+" "+(x1*2)+","+y1+" "+x1+","+(y1*2);
                            polygonEl.setAttribute("points", pathStr);
                            //polygonEl.points=pathStr;
                            break;
                        }
                        case _TOOLBAR_TYPE.table: {
                            var tableEl = parentEl.querySelector("table");
                            tableEl.style.height=dy+"px";
                            tableEl.style.width=dx+"px";
                            break;
                        }
                        default: {

                        }
                    }

                    clearTimeout(_SETTIMEOUT_TARGET);
                    _SETTIMEOUT_TARGET = null;
                }, 10);
            }
        }
        _that.onmouseup = function(_event3){
            clearTimeout(_SETTIMEOUT_TARGET);
            _SETTIMEOUT_TARGET = null;

            _that.onmousemove=null;
            _that.onmouseup=null;
            // 更新描线起点
            // _event3=_event3||window.event;
            // var _target3=_event3.target||_event3.srcElement,
            //     _parentEl3=_target3.parentNode||_target3.parentElement;
            var _parentEl3 = tmpEl.parentNode||tmpEl.parentElement;
            if(_parentEl3&&_parentEl3.id&&_parentEl3.className.indexOf("flow-shape")>=0){
                var timestamp = "" + (new Date()).getTime();
                jsPlumb_instance.updateOffset({ elId: _parentEl3.id, recalc: true, timestamp: timestamp});
                //jsPlumb_instance.draw(_parentEl3.id, null, timestamp);
                //jsPlumb_instance.repaintEverything();
            }
        }
    }

    // 初始化保存添加的布局元素，流程图元素的id
    function initFlowItemIdControls(){
        var $flowItemsAlltype = $(".left-navbar").find('div[id^="cscec"]');
        var flowItemRecordAppend = document.createElement("div");

        var htmlstr="";
        $flowItemsAlltype.each(function(idx, el){
            var curElid=el.id;
            htmlstr+='<input type="hidden" value="0" id="'
                + _DEFAULT_CONFIG.recordidprex+ curElid.replace(/cscec/g, "") +'">';
        });
        flowItemRecordAppend.innerHTML=htmlstr;
        document.body.append(flowItemRecordAppend);
    }

    // 自动生成添加的id
    function getFlowItemtypeId(paramNode){
        var tmpDivid = paramNode.querySelector("div").id;
        var inputRecord = document.getElementById(_DEFAULT_CONFIG.recordidprex+tmpDivid.replace(/cscec/g, ""));
        var tmpid = (+inputRecord.value);
        inputRecord.value=(tmpid+1);
        return _DEFAULT_CONFIG.recordidprex+tmpDivid.replace(/cscec/g, "") + tmpid;
    }

    // 文档流加载完成后
    $(function(){
        //var _ELEMENT_MOVING = null;

        // 左侧流程组件栏，拖拽事件监听，事件代理，向上冒泡
        document.querySelector("#layoutControls").onmousedown = function(e){
            var _that = this,
                ev=e || window.event;
            var target=ev.target||ev.srcElement;
            if(target.nodeName === "SPAN" || target.tagName === "SPAN"){
                var closestnode = similarjQueryClosest(target, ".nav-item");
                // 此处是声明document的鼠标事件，而不是移动对象的鼠标事件，移动对象的鼠标事件仅仅在其父div内部
                document.onmousemove = function(event_2){
                    var appendEl = document.querySelector(".append-dragging-node");
                    if(appendEl){
                    }else{
                        var layoutEl = document.getElementById("layoutControls");
                        // appendEl = document.createElement("div");
                        // appendEl.className = "append-dragging-node";
                        // appendEl.innerHTML = "我是拖动的内容";
                        // layoutEl.appendChild(appendEl);
                        if('content' in document.createElement('template')){
                            var tlelement = closestnode.querySelector("template");
                            var clonefragment = document.importNode(tlelement.content, true);
                            appendEl = clonefragment.querySelector("div");
                            appendEl.className = "append-dragging-node";
                            layoutEl.appendChild(clonefragment);
                        }else{
                            //ie不支持template,其他方法实现
                        }
                    }
                    event_2 = event_2 || window.event;
                    var left = event_2.clientX,
                        top = event_2.clientY-40;
                    appendEl.style.left = left + 'px';
                    appendEl.style.top = top + 'px'
                }
                
                document.onmouseup = function(event_3){
                    event_3 = event_3 || window.event;
                    var uptarget = event_3.target || event_3.srcElement;
                    // 添加页面布局拖拽的对象到画布
                    if(uptarget.className === "flow-target"){
                        addDragContenttoTarget(closestnode, event_3, _TOOLBAR_TYPE.layout);  
                    }
                    document.onmousemove = null;
                    document.onmouseup = null;
                    var draggingdiv = document.querySelector(".append-dragging-node");
                    if(draggingdiv){
                        var layoutEl = document.getElementById("layoutControls");
                        layoutEl.removeChild(draggingdiv);
                    }
                }
            }
            // 阻止默认事件，防止文本内容被选中
            ev.preventDefault();
            //return false;
        }

        // document.querySelector("#layoutControls").onmousemove = function(e){
        //     var ev=e||window.event;
        //     var target=ev.target||ev.srcElement;
        // }
        // document.querySelector("#layoutControls").ondragstart = function(e){
        //     var ev = e || window.event;
        //     var target = ev.target ||　ev.srcElement;
        //     ev.dataTransfer.setData('Text', e.target.id);
        //     target.querySelector(".content-view").style.display="block";
        //     target.querySelector(".preview").style.display = "none";
        // }

        document.querySelector("#flowControls").ondragstart = function(e){
            var ev = e || window.event;
            var target = ev.target ||　ev.srcElement;
            //var curid = target.id;
            ev.dataTransfer.setData('Text', e.target.id);
        }

        /*
        var dragcontent = document.getElementById('csceccontent');
        dragcontent.ondragstart = handle_start;
        dragcontent.ondrag = handle_drag;
        dragcontent.ondragend = handle_end;
        function handle_start(e){
            var ev = e || window.event;
            ev.dataTransfer.setData('Text', e.target.id);
        }
        */

        // 画布目标对象
        var targetCanvas = document.querySelector('.flow-target');
        //targetCanvas.ondragenter = handle_enter;
        //targetCanvas.ondragleave = handle_leave;
        targetCanvas.ondragover = target_handle_over;    //拖拽对象在目标画布下移动事件
        targetCanvas.ondrop = target_handle_drop;    //拖拽对象在目标画布放下事件
        targetCanvas.onmousedown = target_handle_down;
        targetCanvas.ondblclick = target_handle_dbclick;

        // 必须声明ondragover，否则无法将拖动的对象放置到目的地
        function target_handle_over(e) {
            var ev = e || window.event;
            ev.preventDefault();
        }
        function target_handle_drop(e) {
            //console.log('handle_drop-当元素在目的地放下时触发');
            var ev = e || window.event;
            var dragsrc = ev.dataTransfer.getData('Text');
            var dragobj = document.getElementById(dragsrc);
            addDragContenttoTarget(dragobj, ev, _TOOLBAR_TYPE.flow);

            ev.preventDefault()
        }
        function target_handle_down(e){
            var _that=this;
            e = e||window.event;
            var target = e.target||e.srcElement;
            // 拖拽缩放监听事件
            if(target.className==="ui-resizable-icon"){
                resizableTarget(_that, target);
            }
            // 拖拽移动事件
            // if(target.hasAttribute("controltype")){
            //     document.onmousemove = function(_event2){
            //         _event2=_event2||window.event;
            //         var ctop = _event2.clientY-_FLOWSHAPE_CONFIG.toptbarheight-10,
            //             cleft = _event2.clientX-_FLOWSHAPE_CONFIG.lefttbarwidth-10;
            //         ctop = ctop<0?0:ctop;
            //         cleft = cleft<0?0:cleft;
            //         target.style.top=ctop+"px";
            //         target.style.left=cleft+"px";
            //         e.preventDefault()
            //     }
            //     document.onmouseup = function(_event3){
            //         document.onmousemove=null;
            //         document.onmouseup=null;
            //     }
            // }
            // 阻止事件向上冒泡
            e.stopPropagation();
        }

        function target_handle_dbclick(e){
            e=e||window.event;
            e.preventDefault();
            e.stopPropagation();
            var target=e.target||e.srcElement;

            var rlTarget = similarjQueryClosest(target, "div[controltype]", true);
            if(rlTarget){
                setPropertyForContrl(rlTarget, rlTarget.getAttribute("controltype"));
            }
        }

        // 滚动监听事件
        document.onscroll=function(e){
            document.body.style.height=document.documentElement.scrollHeight+"px";
        };

        // jsPlumb初始化监听事件
        // addjsPlumbStartline(document.getElementById("jsPlumb_2_1"));
        // addjsPlumbStartline(document.getElementById("jsPlumb_2_2"));
        // 绑定添加连接操作
        jsPlumb_instance.bind("connection", function (info) {
            // info.connection.getOverlay("label").setLabel(info.connection.id);
        });

        // 初始化添加工具栏中布局，元素等内容的id
        initFlowItemIdControls();
    });

    // 双击属性事件
    function setPropertyForContrl(rlElement, controltype){
        debugger;
        var layerOption = {
            title: "属性配置",
            type: 1,
            area: ['700px', '450px'],
            btn: ['确定', '取消'],
            fixed: false,
            content: null,
            yes: function(type, $layerEl){
            }
        };

        switch(controltype){
            case "table": {
                $.get(_DEFAULT_CONFIG.proppathurl+"table-property.htm", function (ret) {
                    var options = Object.assign(layerOption, {
                        title: "table - 属性配置",
                        content: ret,
                        yes: function(idxType, $layerEl){
                            var rows = +$layerEl.find("#rownums").val(),
                                cols = +$layerEl.find("#colnums").val();
                            //table thead
                            var theadvals = $layerEl.find("#theadcontent").val();
                            if(theadvals){
                                theadvals=theadvals.replace(/；/g, ";");
                                var theadvalArr = theadvals.split(";");
                                var rowths="";
                                for(var j=0;j<cols;j++){
                                    if(theadvalArr.length>j)
                                        rowths += "<th>"+theadvalArr[j]+"</th>";
                                    else rowths += "<th></th>";
                                }
                                var rowtrEl_th = document.createElement("tr");
                                rowtrEl_th.innerHTML = rowths;
                                var theadEl = rlElement.querySelector("thead");
                                theadEl.innerHTML = "";
                                theadEl.appendChild(rowtrEl_th);    
                            }
                            //table body
                            rlElement.style.width=150*cols + "px";
                            rlElement.style.height=100*rows + "px";
                            var rowtds = "";
                            while(cols>0){
                                rowtds += "<td></td>";
                                cols--;
                            }
                            var rowtrEl = document.createElement("tr");
                            rowtrEl.className = "table-tr";
                            rowtrEl.style.height = "100px";
                            rowtrEl.style.width = "150px";
                            rowtrEl.innerHTML = rowtds;

                            var appendfragment = document.createDocumentFragment();
                            while(rows>0){
                                var cloneEl = rowtrEl.cloneNode(true);
                                appendfragment.appendChild(cloneEl);
                                rows--;
                            }
                            var tbodyEl = rlElement.querySelector("tbody");
                            tbodyEl.innerHTML = "";
                            tbodyEl.appendChild(appendfragment);

                            //var parentEl = rlElement.parentNode || rlElement.parentElement;
                            // 关闭弹窗
                            layer.close(idxType);
                        }
                    });
                    layer.open(options);
                });
                break;
            }
            default: {

            }
        }
    }

})(jQuery, jsPlumb);